home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / string.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  14.4 KB  |  526 lines

  1. /*{{{}}}*/
  2. /*{{{  #includes*/
  3. #ifdef CONFIG_H
  4. #  include "config.h"
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. #include <limits.h>
  11. #include <signal.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14.  
  15. #define STRING_C
  16. #define I_BUFFLOOP_C
  17. #define I_DISPLAY_C
  18. #define I_FINDS_C
  19. #define I_FILEC_C
  20. #define I_GETMSG_C
  21. #define I_GETTK_C
  22. #define I_MESSAGES_C
  23. #define I_ORIEDT_C
  24. #define I_PROMPT_C
  25.  
  26. #include "origami.h"
  27. #include <lib/ori_add_lib.h>
  28. /*}}}  */
  29.  
  30. #ifdef REGEXP
  31. # include <lib/ori_re_lib.h>
  32.   /*{{{  regular search/replace*/
  33.   /*{{{  variables*/
  34. #  define PAT_NUM (PAT_COUNT+1)
  35.   private regmatch_t matches[PAT_NUM+1];
  36.   private regex_t *ppreg;
  37.   private int nmatches;
  38.   private int r_c_e;
  39.   public boolean preg_ok=False;
  40.   /*}}}  */
  41.  
  42.   /*{{{  reg_comp*/
  43.   private boolean reg_comp(boolean full_action,boolean inverse)
  44.   {
  45.     /*{{{  variables*/
  46. #    ifdef REG_COMP_BUFF
  47.        static struct pr_buff
  48.         { unsigned char s[LINELEN+1];
  49.           reg_types mode;
  50.           boolean full;
  51.           regex_t prog;
  52.         } pr_list[REG_COMP_BUFF];
  53.        static int pr_b_used=0;
  54.        static int pr_b_free=0;
  55. #    else
  56.        static regex_t preg;
  57. #    endif
  58.     int i_t_l_f_offset;
  59.     /*}}}  */
  60.  
  61.     /*{{{  check inverse search!*/
  62.     inverted_search=False;
  63.     i_t_l_f_offset=0;
  64.     if
  65.      (   (    reg_type==ext_reg
  66.            && item_to_look_for[0]=='!'
  67.          )
  68.       || (    reg_type==basic_reg
  69.            && item_to_look_for[0]=='\\'
  70.            && item_to_look_for[1]=='!'
  71.          )
  72.      )
  73.      { if (inverse)
  74.         { inverted_search=True;
  75.           i_t_l_f_offset=(reg_type==ext_reg)?1:2;
  76.         }
  77.        else
  78.         { r_c_e=REG_BADRPT;
  79.           return(True);
  80.         }
  81.      }
  82.     /*}}}  */
  83.     /*{{{  get pr_list*/
  84. #    ifdef REG_COMP_BUFF
  85.        { int i;
  86.  
  87.          /*{{{  return, if already defined*/
  88.          for (i=0;i<pr_b_used;i++)
  89.             if
  90.              (    pr_list[i].mode==reg_type
  91.                && (!full_action || pr_list[i].full)
  92.                && !ustrcmp(item_to_look_for+i_t_l_f_offset,pr_list[i].s)
  93.              )
  94.              { preg_ok=True;
  95.                ppreg= &pr_list[i].prog;
  96.                return(False);
  97.              }
  98.          /*}}}  */
  99.          /*{{{  delete entry*/
  100.          if (pr_b_used==REG_COMP_BUFF)
  101.           { if (pr_b_free==REG_COMP_BUFF)
  102.                pr_b_free=0;
  103.             regfree(&pr_list[pr_b_free].prog);
  104.             pr_b_used--;
  105.           }
  106.          /*}}}  */
  107.          preg_ok=False;
  108.          ppreg= &pr_list[pr_b_free].prog;
  109.        }
  110. #    else
  111.        ppreg= &preg;
  112.        if (preg_ok)
  113.         { regfree(ppreg);
  114.           preg_ok=False;
  115.         }
  116. #    endif
  117.     /*}}}  */
  118.     nmatches=full_action?PAT_NUM:1;
  119.     switch
  120.      /*{{{  regcomp(item_to_look_for,...)*/
  121.      ( r_c_e=regcomp
  122.               ( ppreg,
  123.                 (char*)item_to_look_for+i_t_l_f_offset,
  124.                   USE_NOSUB(full_action)
  125.                 | (reg_type==ext_reg?REG_EXTENDED:0)
  126.                 | USE_SUB_LIMIT(PAT_NUM,*ppreg)
  127.               )
  128.      )
  129.      /*}}}  */
  130.      {
  131.        /*{{{  0 -> ok*/
  132.        case 0:
  133.           preg_ok=True;
  134.           break;
  135.        /*}}}  */
  136.        /*{{{  REG_ESPACE -> ori_abort and error*/
  137.        case REG_ESPACE:
  138.           ocl_msg("REG_ESPACE error",0);
  139.           ori_abort(~SIGINT);
  140.           break;
  141.        /*}}}  */
  142.        /*{{{  else -> error*/
  143.        default:
  144.           regfree(ppreg);
  145.           break;
  146.        /*}}}  */
  147.      }
  148.     /*{{{  save program*/
  149. #    ifdef REG_COMP_BUFF
  150.        if (preg_ok)
  151.         { pr_list[pr_b_free].mode=reg_type;
  152.           pr_list[pr_b_free].full=full_action;
  153.           ustrcpy(pr_list[pr_b_free].s,item_to_look_for+i_t_l_f_offset);
  154.           pr_b_used++;
  155.           pr_b_free++;
  156.         }
  157. #    endif
  158.     /*}}}  */
  159.  
  160.     return(!preg_ok);
  161.   }
  162.   /*}}}  */
  163.   /*{{{  reg_ustrstr*/
  164.   public unsigned char *reg_ustrstr(unsigned char *s,boolean sl,boolean el)
  165.   {
  166.     if (preg_ok)
  167.      { switch
  168.         /*{{{  regexec(ppreg,s,..)*/
  169.         ( regexec
  170.            ( ppreg,
  171.              (char*)s,
  172.              (size_t)nmatches,
  173.              matches,
  174.              (sl?0:REG_NOTBOL)|(el?0:REG_NOTEOL)
  175.            )
  176.         )
  177.         /*}}}  */
  178.         { case 0:
  179.              return((unsigned char*)matches[0].rm_sp);
  180.           default:
  181.              ocl_msg("strstr error",0);
  182.              ori_abort(~SIGINT);
  183.           case REG_NOMATCH:
  184.              break;
  185.         }
  186.      }
  187.     return(0);
  188.   }
  189.   /*}}}  */
  190.   /*{{{  reg_repl*/
  191.   /*{{{  variables*/
  192.   static unsigned char const *r_r_exp_ptr;
  193.   static unsigned char const *r_r_old_ptr;
  194.   static unsigned char *r_r_buff_ptr;
  195.   static unsigned char r_r_added;
  196.   static int r_r_buflen;
  197.   /*}}}  */
  198.   /*{{{  rec_reg_repl*/
  199.   /*{{{  add_repl_char*/
  200.   private boolean add_repl_char(unsigned char c)
  201.   {
  202.     if ((r_r_added=c))
  203.        if (r_r_buflen<=0)
  204.           return(True);
  205.        else
  206.         { *r_r_buff_ptr++=r_r_added;
  207.           r_r_buflen--;
  208.         }
  209.     return(False);
  210.   }
  211.   /*}}}  */
  212.   private unsigned char *rec_reg_repl(int replen,boolean complex,boolean pad)
  213.   {
  214.     /*{{{  variables*/
  215.     unsigned char *r_start_err;
  216.     unsigned char *r_pat_start_err;
  217.     /*}}}  */
  218.  
  219.     for (r_pat_start_err=(unsigned char*)r_r_exp_ptr;;)
  220.      { unsigned char c;
  221.  
  222.        switch((c= *(r_start_err=(unsigned char*)r_r_exp_ptr)))
  223.         { case '\0':
  224.            /*{{{  end replace gen or error, if inside \{} expression*/
  225.              if (complex)
  226.               { r_start_err=r_pat_start_err-3;
  227.                 goto r_r_error;
  228.               }
  229.              *r_r_buff_ptr='\0';
  230.              return(r_r_buff_ptr);
  231.            /*}}}  */
  232.           case '\\':
  233.            /*{{{  handle pattern recall statements*/
  234.            { boolean r_l_complex;
  235.              boolean r_l_pad;
  236.              boolean r_l_used;
  237.              boolean r_l_upper;
  238.              boolean r_l_lower;
  239.  
  240.              r_l_upper=r_l_lower=r_l_complex=False;
  241.              switch(c= *++r_r_exp_ptr)
  242.               {
  243.                 /*{{{  \\ or \} or \0*/
  244.                 case '0':
  245.                    c='\0';
  246.                 case '}':
  247.                    if (!complex)
  248.                        goto r_r_error;
  249.                 case '\\':
  250.                    break;
  251.                    /* add in surrounding switch! */
  252.                 /*}}}  */
  253.                 /*{{{  \un  use uppercase from \n*/
  254.                 case 'u':
  255.                    r_l_upper=True;
  256.                    c= *++r_r_exp_ptr;
  257.                    goto pattern_expr;
  258.                 /*}}}  */
  259.                 /*{{{  \ln  use lowercase from \n*/
  260.                 case 'l':
  261.                    r_l_lower=True;
  262.                    c= *++r_r_exp_ptr;
  263.                    goto pattern_expr;
  264.                 /*}}}  */
  265.                 /*{{{  \{n  } expression, start complex and padding*/
  266.                 case '{':
  267.                    r_l_complex=True;
  268.                    r_l_pad=True;
  269.                    r_l_used=False;
  270.                    c= *++r_r_exp_ptr;
  271.                    r_r_added=' ';
  272.                    goto pattern_expr;
  273.                 /*}}}  */
  274.                 /*{{{  \?n  } expression, start complex , if n used!*/
  275.                 case '?':
  276.                    r_l_complex=True;
  277.                    r_l_pad=False;
  278.                    r_l_used=True;
  279.                    c= *++r_r_exp_ptr;
  280.                    goto pattern_expr;
  281.                 /*}}}  */
  282.                 /*{{{  \!n  } expression, start complex , if n not used!*/
  283.                 case '!':
  284.                    r_l_complex=True;
  285.                    r_l_pad=False;
  286.                    r_l_used=False;
  287.                    c= *++r_r_exp_ptr;
  288.                    goto pattern_expr;
  289.                 /*}}}  */
  290.                 /*{{{  a pattern expression \n*/
  291.                 pattern_expr:
  292.                 default:
  293.                  { int n;
  294.  
  295.                    /*{{{  decode number to n, r_r_exp_ptr to last digit*/
  296.                    { boolean ext_back_used;
  297.  
  298.                      for (n=0,ext_back_used=False;;c= *++r_r_exp_ptr)
  299.                       { switch(c)
  300.                          { case C_BACKREF:
  301.                             /*{{{  mark \g usage*/
  302.                               if (ext_back_used)
  303.                                  goto r_r_error;
  304.                               ext_back_used=True;
  305.                               continue;
  306.                             /*}}}  */
  307.                            default:
  308.                             /*{{{  handle current digit*/
  309.                             { int i;
  310.  
  311.                               /*{{{  test for digit*/
  312.                               for (i=9;;)
  313.                                  if (hex_digits[i]==c)
  314.                                     break;
  315.                                  else if (i)
  316.                                     i--;
  317.                                  else
  318.                                     goto r_r_error;
  319.                               /*}}}  */
  320.                               /*{{{  n=id for pattern*/
  321.                               if (ext_back_used)
  322.                                { ext_back_used=False;
  323.                                  n+=i;
  324.                                  n*=10;
  325.                                  continue;
  326.                                }
  327.                               n+=i;
  328.                               /*}}}  */
  329.                               break;
  330.                             }
  331.                             /*}}}  */
  332.                          }
  333.                         break;
  334.                       }
  335.                    }
  336.                    /*}}}  */
  337.                    r_r_exp_ptr++;
  338.                    if (r_l_complex)
  339.                     /*{{{  gen sub string, cut at given length*/
  340.                     { unsigned char *b;
  341.                       int l;
  342.  
  343.                       b=r_r_buff_ptr;
  344.                       if (r_l_pad)
  345.                        { if (!matches[n].rm_ep || !matches[n].rm_sp)
  346.                             goto r_r_error;
  347.                          l=matches[n].rm_ep-matches[n].rm_sp;
  348.                          if (l>replen)
  349.                             l=replen;
  350.                        }
  351.                       else if (matches[n].rm_sp && matches[n].rm_ep)
  352.                          l=r_l_used?replen:0;
  353.                       else
  354.                          l=r_l_used?0:replen;
  355.                       if (!rec_reg_repl(l,True,r_l_pad))
  356.                          return(0);
  357.                       replen-=r_r_buff_ptr-b;
  358.                     }
  359.                     /*}}}  */
  360.                    else if (replen>0)
  361.                     /*{{{  copy pattern*/
  362.                     { unsigned char *s;
  363.                       int l;
  364.  
  365.                       if (!matches[n].rm_ep || !matches[n].rm_sp)
  366.                          goto r_r_error;
  367.                       s=(unsigned char*)matches[n].rm_sp;
  368.                       l=matches[n].rm_ep-(char*)s;
  369.                       s=(unsigned char*)r_r_old_ptr+(s-(unsigned char*)matches[0].rm_sp);
  370.                       while (l-- && replen-->0)
  371.                        { c= *s++;
  372.                          if (r_l_upper) c=toupper(c);
  373.                          if (r_l_lower) c=tolower(c);
  374.                          if (add_repl_char(c))
  375.                             goto r_r_error;
  376.                        }
  377.                     }
  378.                     /*}}}  */
  379.                    continue;
  380.                  }
  381.                 /*}}}  */
  382.               }
  383.            }
  384.            /*}}}  */
  385.           default:
  386.            /*{{{  in pattern replace, } marks the end of the string!*/
  387.              if (c=='}' && complex)
  388.               { r_r_exp_ptr++;
  389.                 /*{{{  maybe pad the string*/
  390.                 if (pad)
  391.                    while (replen)
  392.                       if (replen && (replen--,add_repl_char(r_r_added)))
  393.                          goto r_r_error;
  394.                 /*}}}  */
  395.  
  396.                 return(r_r_buff_ptr);
  397.               }
  398.            /*}}}  */
  399.            /*{{{  add char*/
  400.              if (replen && (replen--,add_repl_char(c)))
  401.                 goto r_r_error;
  402.              r_r_exp_ptr++;
  403.              continue;
  404.            /*}}}  */
  405.         }
  406.        break;
  407.      }
  408.   r_r_error:
  409.     message(get_msg(M_REG_PAT,r_start_err));
  410.     return(0);
  411.   }
  412.   /*}}}  */
  413.  
  414.   private int reg_repl
  415.    ( unsigned char const * const rep,
  416.      unsigned char *buff,
  417.      unsigned char const * const old
  418.    )
  419.   {
  420.     r_r_exp_ptr=(unsigned char*)rep;
  421.     r_r_old_ptr=old;
  422.     r_r_buff_ptr=buff;
  423.     r_r_buflen=LINELEN;
  424.     buff=rec_reg_repl(LINELEN+1,False,False);
  425.  
  426.     return(buff?(matches[0].rm_ep-matches[0].rm_sp):-1);
  427.   }
  428.   /*}}}  */
  429.   /*}}}  */
  430. #endif
  431. /*{{{  get_search*/
  432. public int get_search(boolean init,boolean full_action,boolean inverse)
  433. {
  434.   unsigned char s[LINELEN+1];
  435.   int result=0;
  436.  
  437. #ifdef REGEXP
  438.   inverted_search=False;
  439.   if (init)
  440.      goto initialized;
  441. #endif
  442.   s_readprompt(s,get_msg(M_SEARCH),LINELEN,search_history);
  443.   for (;;)
  444.    { if (aborted)
  445.       { *item_to_look_for='\0';break; }
  446.      else
  447.       { ustrcpy(item_to_look_for,s);
  448. #       ifdef REGEXP
  449. initialized:
  450.            if (reg_type!=no_reg && reg_comp(full_action,inverse) && !aborted)
  451.             { if (init)
  452.                  result=r_c_e;
  453.               else
  454.                /*{{{  ask again and continue*/
  455.                { readprompt
  456.                   ( s,
  457.                     get_msg(M_REG_EXP,REG_ERR_TAG(r_c_e)),
  458.                     LINELEN,
  459.                     search_history,
  460.                     item_to_look_for,
  461.                     REG_ERR_OFF(*ppreg)
  462.                   );
  463.                  continue;
  464.                }
  465.                /*}}}  */
  466.             }
  467. #       endif
  468.       }
  469.     break;
  470.    }
  471.   return(result);
  472. }
  473. /*}}}  */
  474. /*{{{  strsub*/
  475. public unsigned char *strsub(unsigned char const *s,int off)
  476. {
  477.   while (--off>0 && *s) s++;                 /* skip up to off leading chars */
  478.   return((unsigned char*)s);
  479. }
  480. /*}}}  */
  481. /*{{{  proc_replace*/
  482. public int proc_replace
  483.             ( int ls,
  484.               unsigned char const * const replace,
  485.               unsigned char *line,
  486.               int position,
  487.               int length
  488.             )
  489. { unsigned char repl_string[LINELEN + 1];
  490.   int lr,ll;
  491.  
  492. # ifdef REGEXP
  493.      if (reg_type!=no_reg)
  494.       { if ((ls=reg_repl(replace,repl_string,line+position))<0)
  495.            return(-1);
  496.       }
  497.      else
  498. # endif
  499.         ustrcpy(repl_string,replace);
  500.   ll=ustrlen(line);
  501.   if (ll < position + ls - 1)
  502.      return(0);
  503.   lr=ustrlen(repl_string);
  504.   if (length-ll-lr+ls>=0)
  505.    { ustrcat(repl_string,line+(position+ls));
  506.      ustrcpy(line+position,repl_string);
  507.      trailing_spaces(line);
  508.      return(lr);
  509.    }
  510.   msg_message(M_LONG_LINE);
  511.   return(-1);
  512. }
  513. /*}}}  */
  514. /*{{{  do_file_c*/
  515. public char *do_file_c(char *f)
  516. {
  517.   if ((f=filec(f)))
  518.      push_str_macro((unsigned char*)f);
  519.   else
  520.      f=(char*)empty_text;
  521.   ocl_var[var_ocl_arg].v=strlen(f);
  522.  
  523.   return(f);
  524. }
  525. /*}}}  */
  526.